package com.macro.mall.service.impl;

import com.macro.mall.dto.DashboardStatsDTO;
import com.macro.mall.dto.DashboardTrendDTO;
import com.macro.mall.mapper.XhsOrderMapper;
import com.macro.mall.service.DashboardService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 数据看板服务实现类
 * Created by AI on 2025/09/15.
 */
@Slf4j
@Service
public class DashboardServiceImpl implements DashboardService {
    
    @Resource
    private XhsOrderMapper xhsOrderMapper;
    
    @Override
    public DashboardStatsDTO getStats(LocalDate startDate, LocalDate endDate) {
        log.info("获取数据看板统计，时间范围：{} - {}", startDate, endDate);
        
        DashboardStatsDTO stats = new DashboardStatsDTO();
        
        try {
            // 查询当前时间段数据
            Map<String, Object> currentStats = xhsOrderMapper.getDashboardStats(startDate, endDate);
            
            // 计算上一时间段的日期范围（用于环比计算）
            long daysBetween = ChronoUnit.DAYS.between(startDate, endDate) + 1;
            LocalDate prevStartDate = startDate.minusDays(daysBetween);
            LocalDate prevEndDate = startDate.minusDays(1);
            
            // 查询上一时间段数据
            Map<String, Object> prevStats = xhsOrderMapper.getDashboardStats(prevStartDate, prevEndDate);
            
            // 设置当前数据
            stats.setGmv(getBigDecimalValue(currentStats, "gmv"));
            stats.setTotalOrders(getLongValue(currentStats, "totalOrders"));
            stats.setPayingUsers(getLongValue(currentStats, "payingUsers"));
            
            // 计算环比增长率
            stats.setGmvGrowthRate(calculateGrowthRate(
                getBigDecimalValue(currentStats, "gmv"),
                getBigDecimalValue(prevStats, "gmv")
            ));
            
            stats.setOrdersGrowthRate(calculateGrowthRate(
                new BigDecimal(getLongValue(currentStats, "totalOrders")),
                new BigDecimal(getLongValue(prevStats, "totalOrders"))
            ));
            
            stats.setUsersGrowthRate(calculateGrowthRate(
                new BigDecimal(getLongValue(currentStats, "payingUsers")),
                new BigDecimal(getLongValue(prevStats, "payingUsers"))
            ));
            
            log.info("数据统计完成，GMV：{}，订单数：{}，用户数：{}", 
                stats.getGmv(), stats.getTotalOrders(), stats.getPayingUsers());
            
        } catch (Exception e) {
            log.error("获取数据看板统计失败", e);
            // 返回默认值
            stats.setGmv(BigDecimal.ZERO);
            stats.setTotalOrders(0L);
            stats.setPayingUsers(0L);
            stats.setGmvGrowthRate(BigDecimal.ZERO);
            stats.setOrdersGrowthRate(BigDecimal.ZERO);
            stats.setUsersGrowthRate(BigDecimal.ZERO);
        }
        
        return stats;
    }
    
    @Override
    public DashboardTrendDTO getTrend(LocalDate startDate, LocalDate endDate) {
        log.info("获取数据看板趋势，时间范围：{} - {}", startDate, endDate);
        
        DashboardTrendDTO trend = new DashboardTrendDTO();
        
        try {
            // 判断聚合类型
            long daysBetween = ChronoUnit.DAYS.between(startDate, endDate) + 1;
            String aggregationType;
            List<Map<String, Object>> trendData;
            
            if (daysBetween == 1) {
                // 今天：按小时聚合
                aggregationType = "hour";
                trendData = xhsOrderMapper.getDashboardTrendByHour(startDate, endDate);
            } else if (daysBetween <= 31) {
                // 31天以内：按天聚合
                aggregationType = "day";
                trendData = xhsOrderMapper.getDashboardTrendByDay(startDate, endDate);
            } else {
                // 超过31天：按周聚合
                aggregationType = "week";
                trendData = xhsOrderMapper.getDashboardTrendByWeek(startDate, endDate);
            }
            
            trend.setAggregationType(aggregationType);
            
            // 解析趋势数据
            List<String> labels = new ArrayList<>();
            List<BigDecimal> gmvData = new ArrayList<>();
            List<Long> orderData = new ArrayList<>();
            
            DateTimeFormatter formatter = getFormatterByType(aggregationType);
            
            for (Map<String, Object> item : trendData) {
                String timeLabel = getStringValue(item, "timeLabel");
                labels.add(formatTimeLabel(timeLabel, aggregationType));
                gmvData.add(getBigDecimalValue(item, "gmv"));
                orderData.add(getLongValue(item, "orders"));
            }
            
            trend.setLabels(labels);
            trend.setGmvData(gmvData);
            trend.setOrderData(orderData);
            
            log.info("趋势数据获取完成，聚合类型：{}，数据点数：{}", aggregationType, labels.size());
            
        } catch (Exception e) {
            log.error("获取数据看板趋势失败", e);
            // 返回空数据
            trend.setLabels(new ArrayList<>());
            trend.setGmvData(new ArrayList<>());
            trend.setOrderData(new ArrayList<>());
            trend.setAggregationType("day");
        }
        
        return trend;
    }
    
    /**
     * 计算环比增长率
     */
    private BigDecimal calculateGrowthRate(BigDecimal current, BigDecimal previous) {
        if (previous == null || previous.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        
        if (current == null) {
            return new BigDecimal("-100");
        }
        
        return current.subtract(previous)
            .divide(previous, 4, BigDecimal.ROUND_HALF_UP)
            .multiply(new BigDecimal("100"))
            .setScale(1, BigDecimal.ROUND_HALF_UP);
    }
    
    /**
     * 根据聚合类型获取时间格式器
     */
    private DateTimeFormatter getFormatterByType(String aggregationType) {
        switch (aggregationType) {
            case "hour":
                return DateTimeFormatter.ofPattern("HH:mm");
            case "day":
                return DateTimeFormatter.ofPattern("MM-dd");
            case "week":
                return DateTimeFormatter.ofPattern("MM-dd");
            default:
                return DateTimeFormatter.ofPattern("MM-dd");
        }
    }
    
    /**
     * 格式化时间标签
     */
    private String formatTimeLabel(String timeLabel, String aggregationType) {
        if (timeLabel == null) return "";
        
        try {
            switch (aggregationType) {
                case "hour":
                    return timeLabel + ":00";
                case "day":
                    return timeLabel;
                case "week":
                    return "第" + timeLabel + "周";
                default:
                    return timeLabel;
            }
        } catch (Exception e) {
            return timeLabel;
        }
    }
    
    /**
     * 安全获取BigDecimal值
     */
    private BigDecimal getBigDecimalValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return BigDecimal.ZERO;
        }
        if (value instanceof BigDecimal) {
            return (BigDecimal) value;
        }
        if (value instanceof Number) {
            return new BigDecimal(value.toString());
        }
        try {
            return new BigDecimal(value.toString());
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }
    
    /**
     * 安全获取Long值
     */
    private Long getLongValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        if (value == null) {
            return 0L;
        }
        if (value instanceof Long) {
            return (Long) value;
        }
        if (value instanceof Number) {
            return ((Number) value).longValue();
        }
        try {
            return Long.parseLong(value.toString());
        } catch (NumberFormatException e) {
            return 0L;
        }
    }
    
    /**
     * 安全获取String值
     */
    private String getStringValue(Map<String, Object> map, String key) {
        Object value = map.get(key);
        return value != null ? value.toString() : "";
    }
}
